package biggestloser.servlet;

import java.io.IOException;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import biggestloser.util.DatastoreUtil;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;

import java.util.Properties;
import java.util.logging.Logger;

import javax.mail.Address;
import javax.mail.BodyPart;
import javax.mail.Session; 
import javax.mail.internet.MimeMessage;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMultipart;

/**
 * This servlet handles incoming mail.
 */
public class EmailHandler extends HttpServlet
{
	private static final Logger log = Logger.getLogger(EmailHandler.class.getName());
	
	private static final long serialVersionUID = 3675111461254492650L;

	public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException
    {	
		log.info("Processing email");
		
		// Load mail message
		Address[] from = null;
		InternetAddress email = null;
		String    subj = "";
		String  weight = "";
		String body    = ""; // Only used for error logging
		
		try
		{
			Properties props = new Properties(); 
        	Session session = Session.getDefaultInstance(props, null); 
        	MimeMessage message = new MimeMessage(session, req.getInputStream());
        	
        	from = message.getFrom();
        	subj = message.getSubject();
        	email = (InternetAddress)from[0];
        	
        	log.info("Received email from " + from[0].toString() + " with subject " + subj);
        	
        	if(message.getContent() instanceof MimeMultipart)
        	{
        		log.info("Handling MimeMultipart message");
        		
        		MimeMultipart mm = (MimeMultipart)message.getContent();
        		
        		log.info("# of parts = " + mm.getCount());
        		
        		// The first part should contain the weight as the first "word"
        		BodyPart bp = mm.getBodyPart(0);
        		body = bp.getContent().toString();
        		String parts[] = body.split("\\s");
        		weight = parts[0];
        	}
        	else
        	{
        		log.info("Handling non MimeMultipart message");
        		
        		body = message.getContent().toString();
        		String parts[] = body.split("\\s");
        		weight = parts[0];
        	}
		}
		catch(Exception e)
		{
			log.throwing(EmailHandler.class.toString(), "doPost", e);
			throw new IOException(e.getCause());
		}
		
		// Get the week from the email subject
		String[] parts = subj.split(" ");
		int week = Integer.parseInt(parts[parts.length-1]);

		// Get user from datastore
		Entity user = DatastoreUtil.getUserByEmail(email.getAddress());

		if(user != null)
		{
			log.info("Found user " + user.getProperty("name") + " in datastore");
			
			try
			{
				// Calculate the % change from week 1 here; we do it here so that
				// the various servlets that need this info don't spend time calculating it
				double currWeek = Double.parseDouble(weight);

				// Only calculate change after week 1
				if(week > 1)
				{
					// If admin is resetting to 0.0, reset changed % as well
					double change = 0.0;
					
					if(currWeek != 0.0)
					{
						double week1  = Double.parseDouble(user.getProperty("week1").toString());
						
						// If the 2 weights are the same, we need to avoid an issue where floating
						// point subtraction can cause non-zero deltas, which show up as -0.0%
						if(currWeek == week1)
						{
							change = 0.0;
						}
						else
						{
							change = ((week1 - currWeek) / week1) * -100;
						}
					}
					
					user.setProperty("week" + week + "change", change);
					
					// If this user was previously disabled, set them back to enabled
					// since they're finally sending in an e-mail.
					user.setProperty("status", "enabled");
					
					log.info("Updated % change to " + change);
				}
	    		
				// Always store the raw weight for each week
				user.setProperty("week" + week, currWeek);
				
				DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
				datastore.put(user);
				
				log.info("Successfully updated weight and % change for week " + week);
			}
			catch(Exception e)
			{
				log.severe("Error parsing weight: " + e.getMessage());
				log.severe("body = " + body);
				log.severe("weight string = " + weight);
			}
		}
		else
		{
			log.warning("Unable to find user in datastore for email " + email.getAddress());
		}
    }
	
	public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException
	{
		log.info("No sure how I got here");
	}
}